home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2005 October / PCWOCT05.iso / Software / FromTheMag / XAMPP 1.4.14 / xampp-win32-1.4.14-installer.exe / xampp / php / pear / Date / Span.php < prev    next >
PHP Script  |  2004-10-01  |  31KB  |  940 lines

  1. <?php
  2. // vim: set expandtab tabstop=4 softtabstop=4 shiftwidth=4:
  3. // +----------------------------------------------------------------------+
  4. // | PHP Version 4                                                        |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1997-2003 The PHP Group                                |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 2.02 of the PHP license,      |
  9. // | that is bundled with this package in the file LICENSE, and is        |
  10. // | available at through the world-wide-web at                           |
  11. // | http://www.php.net/license/2_02.txt.                                 |
  12. // | If you did not receive a copy of the PHP license and are unable to   |
  13. // | obtain it through the world-wide-web, please send a note to          |
  14. // | license@php.net so we can mail you a copy immediately.               |
  15. // +----------------------------------------------------------------------+
  16. // | Author: Leandro Lucarella <llucax@php.net>                           |
  17. // +----------------------------------------------------------------------+
  18. //
  19. // $Id: Span.php,v 1.4 2003/04/30 03:56:26 llucax Exp $
  20. //
  21.  
  22. require_once 'Date.php';
  23. require_once 'Date/Calc.php';
  24.  
  25. /**
  26.  * Non Numeric Separated Values (NNSV) Input Format.
  27.  *
  28.  * Input format guessed from something like this:
  29.  * days<sep>hours<sep>minutes<sep>seconds
  30.  * Where <sep> is any quantity of non numeric chars. If no values are
  31.  * given, time span is set to zero, if one value is given, it's used for
  32.  * hours, if two values are given it's used for hours and minutes and if
  33.  * three values are given, it's used for hours, minutes and seconds.<br>
  34.  * Examples:<br>
  35.  * ''                   -> 0, 0, 0, 0 (days, hours, minutes, seconds)<br>
  36.  * '12'                 -> 0, 12, 0, 0
  37.  * '12.30'              -> 0, 12, 30, 0<br>
  38.  * '12:30:18'           -> 0, 12, 30, 18<br>
  39.  * '3-12-30-18'         -> 3, 12, 30, 18<br>
  40.  * '3 days, 12-30-18'   -> 3, 12, 30, 18<br>
  41.  * '12:30 with 18 secs' -> 0, 12, 30, 18<br>
  42.  *
  43.  * @const int
  44.  */
  45. define('DATE_SPAN_INPUT_FORMAT_NNSV', 1);
  46.  
  47. /**
  48.  * Default time format when converting to a string.
  49.  *
  50.  * @global string
  51.  */
  52. $_DATE_SPAN_FORMAT  = '%C';
  53.  
  54. /**
  55.  * Default time format when converting from a string.
  56.  *
  57.  * @global mixed
  58.  */
  59. $_DATE_SPAN_INPUT_FORMAT = DATE_SPAN_INPUT_FORMAT_NNSV;
  60.  
  61. /**
  62.  * Generic time span handling class for PEAR.
  63.  *
  64.  * @package Date
  65.  * @author  Leandro Lucarella <llucax@php.net>
  66.  * @version $Revision: 1.4 $
  67.  * @since   1.4
  68.  * @todo    Get and set default local input and output formats?
  69.  * @access  public
  70.  */
  71. class Date_Span {
  72.  
  73.     /**
  74.      * @var int
  75.      */
  76.     var $day;
  77.  
  78.     /**
  79.      * @var int
  80.      */
  81.     var $hour;
  82.  
  83.     /**
  84.      * @var int
  85.      */
  86.     var $minute;
  87.  
  88.     /**
  89.      * @var int
  90.      */
  91.     var $second;
  92.  
  93.     /**
  94.      * Constructor.
  95.      *
  96.      * Creates the time span object calling the set() method.
  97.      *
  98.      * @param  mixed $time   Time span expression.
  99.      * @param  mixed $format Format string to set it from a string or the
  100.      *                       second date set it from a date diff.
  101.      *
  102.      * @see    set()
  103.      * @access public
  104.      */
  105.     function Date_Span($time = 0, $format = null)
  106.     {
  107.         $this->set($time, $format);
  108.     }
  109.  
  110.     /**
  111.      * Set the time span to a new value in a 'smart' way.
  112.      *
  113.      * Sets the time span depending on the argument types, calling
  114.      * to the appropriate setFromXxx() method.
  115.      *
  116.      * @param  mixed $time   Time span expression.
  117.      * @param  mixed $format Format string to set it from a string or the
  118.      *                       second date set it from a date diff.
  119.      *
  120.      * @return bool  true on success.
  121.      *
  122.      * @see    setFromObject()
  123.      * @see    setFromArray()
  124.      * @see    setFromString()
  125.      * @see    setFromSeconds()
  126.      * @see    setFromDateDiff()
  127.      * @access public
  128.      */
  129.     function set($time = 0, $format = null)
  130.     {
  131.         if (is_a($time, 'date_span')) {
  132.             return $this->copy($time);
  133.         } elseif (is_a($time, 'date') and is_a($format, 'date')) {
  134.             return $this->setFromDateDiff($time, $format);
  135.         } elseif (is_array($time)) {
  136.             return $this->setFromArray($time);
  137.         } elseif (is_string($time)) {
  138.             return $this->setFromString($time, $format);
  139.         } elseif (is_int($time)) {
  140.             return $this->setFromSeconds($time);
  141.         } else {
  142.             return $this->setFromSeconds(0);
  143.         }
  144.     }
  145.  
  146.     /**
  147.      * Set the time span from an array.
  148.      *
  149.      * Set the time span from an array. Any value can be a float (but it
  150.      * has no sense in seconds), for example array(23.5, 20, 0) is
  151.      * interpreted as 23 hours, .5*60 + 20 = 50 minutes and 0 seconds.
  152.      *
  153.      * @param  array $time Items are counted from right to left. First
  154.      *                     item is for seconds, second for minutes, third
  155.      *                     for hours and fourth for days. If there are
  156.      *                     less items than 4, zero (0) is assumed for the
  157.      *                     absent values.
  158.      *
  159.      * @return bool  True on success.
  160.      *
  161.      * @access public
  162.      */
  163.     function setFromArray($time)
  164.     {
  165.         if (!is_array($time)) {
  166.             return false;
  167.         }
  168.         $tmp1 = new Date_Span;
  169.         if (!$tmp1->setFromSeconds(@array_pop($time))) {
  170.             return false;
  171.         }
  172.         $tmp2 = new Date_Span;
  173.         if (!$tmp2->setFromMinutes(@array_pop($time))) {
  174.             return false;
  175.         }
  176.         $tmp1->add($tmp2);
  177.         if (!$tmp2->setFromHours(@array_pop($time))) {
  178.             return false;
  179.         }
  180.         $tmp1->add($tmp2);
  181.         if (!$tmp2->setFromDays(@array_pop($time))) {
  182.             return false;
  183.         }
  184.         $tmp1->add($tmp2);
  185.         return $this->copy($tmp1);
  186.     }
  187.  
  188.     /**
  189.      * Set the time span from a string based on an input format.
  190.      *
  191.      * Set the time span from a string based on an input format. This is
  192.      * some like a mix of format() method and sscanf() PHP function. The
  193.      * error checking and validation of this function is very primitive,
  194.      * so you should be carefull when using it with unknown $time strings.
  195.      * With this method you are assigning day, hour, minute and second
  196.      * values, and the last values are used. This means that if you use
  197.      * something like setFromString('10, 20', '%H, %h') your time span
  198.      * would be 20 hours long. Allways remember that this method set
  199.      * <b>all</b> the values, so if you had a $time span 30 minutes long
  200.      * and you make $time->setFromString('20 hours', '%H hours'), $time
  201.      * span would be 20 hours long (and not 20 hours and 30 minutes).
  202.      * Input format options:<br>
  203.      *  <code>%C</code> Days with time, same as "%D, %H:%M:%S".<br>
  204.      *  <code>%d</code> Total days as a float number
  205.      *                  (2 days, 12 hours = 2.5 days).<br>
  206.      *  <code>%D</code> Days as a decimal number.<br>
  207.      *  <code>%e</code> Total hours as a float number
  208.      *                  (1 day, 2 hours, 30 minutes = 26.5 hours).<br>
  209.      *  <code>%f</code> Total minutes as a float number
  210.      *                  (2 minutes, 30 seconds = 2.5 minutes).<br>
  211.      *  <code>%g</code> Total seconds as a decimal number
  212.      *                  (2 minutes, 30 seconds = 90 seconds).<br>
  213.      *  <code>%h</code> Hours as decimal number.<br>
  214.      *  <code>%H</code> Hours as decimal number limited to 2 digits.<br>
  215.      *  <code>%m</code> Minutes as a decimal number.<br>
  216.      *  <code>%M</code> Minutes as a decimal number limited to 2 digits.<br>
  217.      *  <code>%n</code> Newline character (\n).<br>
  218.      *  <code>%p</code> Either 'am' or 'pm' depending on the time. If 'pm'
  219.      *                  is detected it adds 12 hours to the resulting time
  220.      *                  span (without any checks). This is case
  221.      *                  insensitive.<br>
  222.      *  <code>%r</code> Time in am/pm notation, same as "%H:%M:%S %p".<br>
  223.      *  <code>%R</code> Time in 24-hour notation, same as "%H:%M".<br>
  224.      *  <code>%s</code> Seconds as a decimal number.<br>
  225.      *  <code>%S</code> Seconds as a decimal number limited to 2 digits.<br>
  226.      *  <code>%t</code> Tab character (\t).<br>
  227.      *  <code>%T</code> Current time equivalent, same as "%H:%M:%S".<br>
  228.      *  <code>%%</code> Literal '%'.<br>
  229.      *
  230.      * @param  string $time   String from where to get the time span
  231.      *                        information.
  232.      * @param  string $format Format string.
  233.      *
  234.      * @return bool   True on success.
  235.      *
  236.      * @access public
  237.      */
  238.     function setFromString($time, $format = null)
  239.     {
  240.         if (is_null($format)) {
  241.             $format = $GLOBALS['_DATE_SPAN_INPUT_FORMAT'];
  242.         }
  243.         // If format is a string, it parses the string format.
  244.         if (is_string($format)) {
  245.             $str = '';
  246.             $vars = array();
  247.             $pm = 'am';
  248.             $day = $hour = $minute = $second = 0;
  249.             for ($i = 0; $i < strlen($format); $i++) {
  250.                 $char = $format{$i};
  251.                 if ($char == '%') {
  252.                     $nextchar = $format{++$i};
  253.                     switch ($nextchar) {
  254.                         case 'c':
  255.                             $str .= '%d, %d:%d:%d';
  256.                             array_push(
  257.                                 $vars, 'day', 'hour', 'minute', 'second');
  258.                             break;
  259.                         case 'C':
  260.                             $str .= '%d, %2d:%2d:%2d';
  261.                             array_push(
  262.                                 $vars, 'day', 'hour', 'minute', 'second');
  263.                             break;
  264.                         case 'd':
  265.                             $str .= '%f';
  266.                             array_push($vars, 'day');
  267.                             break;
  268.                         case 'D':
  269.                             $str .= '%d';
  270.                             array_push($vars, 'day');
  271.                             break;
  272.                         case 'e':
  273.                             $str .= '%f';
  274.                             array_push($vars, 'hour');
  275.                             break;
  276.                         case 'f':
  277.                             $str .= '%f';
  278.                             array_push($vars, 'minute');
  279.                             break;
  280.                         case 'g':
  281.                             $str .= '%f';
  282.                             array_push($vars, 'second');
  283.                             break;
  284.                         case 'h':
  285.                             $str .= '%d';
  286.                             array_push($vars, 'hour');
  287.                             break;
  288.                         case 'H':
  289.                             $str .= '%2d';
  290.                             array_push($vars, 'hour');
  291.                             break;
  292.                         case 'm':
  293.                             $str .= '%d';
  294.                             array_push($vars, 'minute');
  295.                             break;
  296.                         case 'M':
  297.                             $str .= '%2d';
  298.                             array_push($vars, 'minute');
  299.                             break;
  300.                         case 'n':
  301.                             $str .= "\n";
  302.                             break;
  303.                         case 'p':
  304.                             $str .= '%2s';
  305.                             array_push($vars, 'pm');
  306.                             break;
  307.                         case 'r':
  308.                             $str .= '%2d:%2d:%2d %2s';
  309.                             array_push(
  310.                                 $vars, 'hour', 'minute', 'second', 'pm');
  311.                             break;
  312.                         case 'R':
  313.                             $str .= '%2d:%2d';
  314.                             array_push($vars, 'hour', 'minute');
  315.                             break;
  316.                         case 's':
  317.                             $str .= '%d';
  318.                             array_push($vars, 'second');
  319.                             break;
  320.                         case 'S':
  321.                             $str .= '%2d';
  322.                             array_push($vars, 'second');
  323.                             break;
  324.                         case 't':
  325.                             $str .= "\t";
  326.                             break;
  327.                         case 'T':
  328.                             $str .= '%2d:%2d:%2d';
  329.                             array_push($vars, 'hour', 'minute', 'second');
  330.                             break;
  331.                         case '%':
  332.                             $str .= "%";
  333.                             break;
  334.                         default:
  335.                             $str .= $char . $nextchar;
  336.                     }
  337.                 } else {
  338.                     $str .= $char;
  339.                 }
  340.             }
  341.             $vals = sscanf($time, $str);
  342.             foreach ($vals as $i => $val) {
  343.                 if (is_null($val)) {
  344.                     return false;
  345.                 }
  346.                 $$vars[$i] = $val;
  347.             }
  348.             if (strcasecmp($pm, 'pm') == 0) {
  349.                 $hour += 12;
  350.             } elseif (strcasecmp($pm, 'am') != 0) {
  351.                 return false;
  352.             }
  353.             $this->setFromArray(array($day, $hour, $minute, $second));
  354.         // If format is a integer, it uses a predefined format
  355.         // detection method.
  356.         } elseif (is_integer($format)) {
  357.             switch ($format) {
  358.                 case DATE_SPAN_INPUT_FORMAT_NNSV:
  359.                     $time = preg_split('/\D+/', $time);
  360.                     switch (count($time)) {
  361.                         case 0:
  362.                             return $this->setFromArray(
  363.                                 array(0, 0, 0, 0));
  364.                         case 1:
  365.                             return $this->setFromArray(
  366.                                 array(0, $time[0], 0, 0));
  367.                         case 2:
  368.                             return $this->setFromArray(
  369.                                 array(0, $time[0], $time[1], 0));
  370.                         case 3:
  371.                             return $this->setFromArray(
  372.                                 array(0, $time[0], $time[1], $time[2]));
  373.                         default:
  374.                             return $this->setFromArray($time);
  375.                     }
  376.                     break;
  377.             }
  378.         }
  379.         return false;
  380.     }
  381.  
  382.     /**
  383.      * Set the time span from a total number of seconds.
  384.      *
  385.      * @param  int  $seconds Total number of seconds.
  386.      *
  387.      * @return bool True on success.
  388.      *
  389.      * @access public
  390.      */
  391.     function setFromSeconds($seconds)
  392.     {
  393.         if ($seconds < 0) {
  394.             return false;
  395.         }
  396.         $sec  = intval($seconds);
  397.         $min  = floor($sec / 60);
  398.         $hour = floor($min / 60);
  399.         $day  = intval(floor($hour / 24));
  400.         $this->second = $sec % 60;
  401.         $this->minute = $min % 60;
  402.         $this->hour   = $hour % 24;
  403.         $this->day    = $day;
  404.         return true;
  405.     }
  406.  
  407.     /**
  408.      * Set the time span from a total number of minutes.
  409.      *
  410.      * @param  float $minutes Total number of minutes.
  411.      *
  412.      * @return bool  True on success.
  413.      *
  414.      * @access public
  415.      */
  416.     function setFromMinutes($minutes)
  417.     {
  418.         return $this->setFromSeconds(round($minutes * 60));
  419.     }
  420.  
  421.     /**
  422.      * Set the time span from a total number of hours.
  423.      *
  424.      * @param  float $hours Total number of hours.
  425.      *
  426.      * @return bool  True on success.
  427.      *
  428.      * @access public
  429.      */
  430.     function setFromHours($hours)
  431.     {
  432.         return $this->setFromSeconds(round($hours * 3600));
  433.     }
  434.  
  435.     /**
  436.      * Set the time span from a total number of days.
  437.      *
  438.      * @param  float $days Total number of days.
  439.      *
  440.      * @return bool  True on success.
  441.      *
  442.      * @access public
  443.      */
  444.     function setFromDays($days)
  445.     {
  446.         return $this->setFromSeconds(round($days * 86400));
  447.     }
  448.  
  449.     /**
  450.      * Set the span from the elapsed time between two dates.
  451.      *
  452.      * Set the span from the elapsed time between two dates. The time span
  453.      * is allways positive, so the date's order is not important.
  454.      * 
  455.      * @param  object Date $date1 First Date.
  456.      * @param  object Date $date2 Second Date.
  457.      *
  458.      * @return bool  True on success.
  459.      *
  460.      * @access public
  461.      */
  462.     function setFromDateDiff($date1, $date2)
  463.     {
  464.         if (!is_a($date1, 'date') or !is_a($date2, 'date')) {
  465.             return false;
  466.         }
  467.         $date1->toUTC();
  468.         $date2->toUTC();
  469.         if ($date1->after($date2)) {
  470.             list($date1, $date2) = array($date2, $date1);
  471.         }
  472.         $days = Date_Calc::dateDiff(
  473.             $date1->getDay(), $date1->getMonth(), $date1->getYear(),
  474.             $date2->getDay(), $date2->getMonth(), $date2->getYear()
  475.         );
  476.         $hours = $date2->getHour() - $date1->getHour();
  477.         $mins  = $date2->getMinute() - $date1->getMinute();
  478.         $secs  = $date2->getSecond() - $date1->getSecond();
  479.         $this->setFromSeconds(
  480.             $days * 86400 + $hours * 3600 + $mins * 60 + $secs
  481.         );
  482.         return true;
  483.     }
  484.  
  485.     /**
  486.      * Set the time span from another time object.
  487.      *
  488.      * @param  object Date_Span $time Source time span object.
  489.      *
  490.      * @return bool   True on success.
  491.      *
  492.      * @access public
  493.      */
  494.     function copy($time)
  495.     {
  496.         if (is_a($time, 'date_span')) {
  497.             $this->second = $time->second;
  498.             $this->minute = $time->minute;
  499.             $this->hour   = $time->hour;
  500.             $this->day    = $time->day;
  501.             return true;
  502.         } else {
  503.             return false;
  504.         }
  505.     }
  506.  
  507.     /**
  508.      * Time span pretty printing (similar to Date::format()).
  509.      *
  510.      * Formats the time span in the given format, similar to
  511.      * strftime() and Date::format().<br>
  512.      * <br>
  513.      * Formatting options:<br>
  514.      *  <code>%C</code> Days with time, same as "%D, %H:%M:%S".<br>
  515.      *  <code>%d</code> Total days as a float number
  516.      *                  (2 days, 12 hours = 2.5 days).<br>
  517.      *  <code>%D</code> Days as a decimal number.<br>
  518.      *  <code>%e</code> Total hours as a float number
  519.      *                  (1 day, 2 hours, 30 minutes = 26.5 hours).<br>
  520.      *  <code>%E</code> Total hours as a decimal number
  521.      *                  (1 day, 2 hours, 40 minutes = 26 hours).<br>
  522.      *  <code>%f</code> Total minutes as a float number
  523.      *                  (2 minutes, 30 seconds = 2.5 minutes).<br>
  524.      *  <code>%F</code> Total minutes as a decimal number
  525.      *                  (1 hour, 2 minutes, 40 seconds = 62 minutes).<br>
  526.      *  <code>%g</code> Total seconds as a decimal number
  527.      *                  (2 minutes, 30 seconds = 90 seconds).<br>
  528.      *  <code>%h</code> Hours as decimal number (0 to 23).<br>
  529.      *  <code>%H</code> Hours as decimal number (00 to 23).<br>
  530.      *  <code>%i</code> Hours as decimal number on 12-hour clock
  531.      *                  (1 to 12).<br>
  532.      *  <code>%I</code> Hours as decimal number on 12-hour clock
  533.      *                  (01 to 12).<br>
  534.      *  <code>%m</code> Minutes as a decimal number (0 to 59).<br>
  535.      *  <code>%M</code> Minutes as a decimal number (00 to 59).<br>
  536.      *  <code>%n</code> Newline character (\n).<br>
  537.      *  <code>%p</code> Either 'am' or 'pm' depending on the time.<br>
  538.      *  <code>%P</code> Either 'AM' or 'PM' depending on the time.<br>
  539.      *  <code>%r</code> Time in am/pm notation, same as "%I:%M:%S %p".<br>
  540.      *  <code>%R</code> Time in 24-hour notation, same as "%H:%M".<br>
  541.      *  <code>%s</code> Seconds as a decimal number (0 to 59).<br>
  542.      *  <code>%S</code> Seconds as a decimal number (00 to 59).<br>
  543.      *  <code>%t</code> Tab character (\t).<br>
  544.      *  <code>%T</code> Current time equivalent, same as "%H:%M:%S".<br>
  545.      *  <code>%%</code> Literal '%'.<br>
  546.      *
  547.      * @param  string $format The format string for returned time span.
  548.      *
  549.      * @return string The time span in specified format.
  550.      *
  551.      * @access public
  552.      */
  553.     function format($format = null)
  554.     {
  555.         if (is_null($format)) {
  556.             $format = $GLOBALS['_DATE_SPAN_FORMAT'];
  557.         }
  558.         $output = '';
  559.         for ($i = 0; $i < strlen($format); $i++) {
  560.             $char = $format{$i};
  561.             if ($char == '%') {
  562.                 $nextchar = $format{++$i};
  563.                 switch ($nextchar) {
  564.                     case 'C':
  565.                         $output .= sprintf(
  566.                             '%d, %02d:%02d:%02d',
  567.                             $this->day,
  568.                             $this->hour,
  569.                             $this->minute,
  570.                             $this->second
  571.                         );
  572.                         break;
  573.                     case 'd':
  574.                         $output .= $this->toDays();
  575.                         break;
  576.                     case 'D':
  577.                         $output .= $this->day;
  578.                         break;
  579.                     case 'e':
  580.                         $output .= $this->toHours();
  581.                         break;
  582.                     case 'E':
  583.                         $output .= floor($this->toHours());
  584.                         break;
  585.                     case 'f':
  586.                         $output .= $this->toMinutes();
  587.                         break;
  588.                     case 'F':
  589.                         $output .= floor($this->toMinutes());
  590.                         break;
  591.                     case 'g':
  592.                         $output .= $this->toSeconds();
  593.                         break;
  594.                     case 'h':
  595.                         $output .= $this->hour;
  596.                         break;
  597.                     case 'H':
  598.                         $output .= sprintf('%02d', $this->hour);
  599.                         break;
  600.                     case 'i':
  601.                         $hour =
  602.                             ($this->hour + 1) > 12 ?
  603.                             $this->hour - 12 :
  604.                             $this->hour;
  605.                         $output .= ($hour == 0) ? 12 : $hour;
  606.                         break;
  607.                     case 'I':
  608.                         $hour =
  609.                             ($this->hour + 1) > 12 ?
  610.                             $this->hour - 12 :
  611.                             $this->hour;
  612.                         $output .= sprintf('%02d', $hour==0 ? 12 : $hour);
  613.                         break;
  614.                     case 'm':
  615.                         $output .= $this->minute;
  616.                         break;
  617.                     case 'M':
  618.                         $output .= sprintf('%02d',$this->minute);
  619.                         break;
  620.                     case 'n':
  621.                         $output .= "\n";
  622.                         break;
  623.                     case 'p':
  624.                         $output .= $this->hour >= 12 ? 'pm' : 'am';
  625.                         break;
  626.                     case 'P':
  627.                         $output .= $this->hour >= 12 ? 'PM' : 'AM';
  628.                         break;
  629.                     case 'r':
  630.                         $hour =
  631.                             ($this->hour + 1) > 12 ?
  632.                             $this->hour - 12 :
  633.                             $this->hour;
  634.                         $output .= sprintf(
  635.                             '%02d:%02d:%02d %s',
  636.                             $hour==0 ?  12 : $hour,
  637.                             $this->minute,
  638.                             $this->second,
  639.                             $this->hour >= 12 ? 'pm' : 'am'
  640.                         );
  641.                         break;
  642.                     case 'R':
  643.                         $output .= sprintf(
  644.                             '%02d:%02d', $this->hour, $this->minute
  645.                         );
  646.                         break;
  647.                     case 's':
  648.                         $output .= $this->second;
  649.                         break;
  650.                     case 'S':
  651.                         $output .= sprintf('%02d', $this->second);
  652.                         break;
  653.                     case 't':
  654.                         $output .= "\t";
  655.                         break;
  656.                     case 'T':
  657.                         $output .= sprintf(
  658.                             '%02d:%02d:%02d',
  659.                             $this->hour, $this->minute, $this->second
  660.                         );
  661.                         break;
  662.                     case '%':
  663.                         $output .= "%";
  664.                         break;
  665.                     default:
  666.                         $output .= $char . $nextchar;
  667.                 }
  668.             } else {
  669.                 $output .= $char;
  670.             }
  671.         }
  672.         return $output;
  673.     }
  674.  
  675.     /**
  676.      * Convert time span to seconds.
  677.      *
  678.      * @return int Time span as an integer number of seconds.
  679.      *
  680.      * @access public
  681.      */
  682.     function toSeconds()
  683.     {
  684.         return $this->day * 86400 + $this->hour * 3600 +
  685.             $this->minute * 60 + $this->second;
  686.     }
  687.  
  688.     /**
  689.      * Convert time span to minutes.
  690.      *
  691.      * @return float Time span as a decimal number of minutes.
  692.      *
  693.      * @access public
  694.      */
  695.     function toMinutes()
  696.     {
  697.         return $this->day * 1440 + $this->hour * 60 + $this->minute +
  698.             $this->second / 60;
  699.     }
  700.  
  701.     /**
  702.      * Convert time span to hours.
  703.      *
  704.      * @return float Time span as a decimal number of hours.
  705.      *
  706.      * @access public
  707.      */
  708.     function toHours()
  709.     {
  710.         return $this->day * 24 + $this->hour + $this->minute / 60 +
  711.             $this->second / 3600;
  712.     }
  713.  
  714.     /**
  715.      * Convert time span to days.
  716.      *
  717.      * @return float Time span as a decimal number of days.
  718.      *
  719.      * @access public
  720.      */
  721.     function toDays()
  722.     {
  723.         return $this->day + $this->hour / 24 + $this->minute / 1440 +
  724.             $this->second / 86400;
  725.     }
  726.  
  727.     /**
  728.      * Adds a time span.
  729.      *
  730.      * @param  object Date_Span $time Time span to add.
  731.      *
  732.      * @access public
  733.      */
  734.     function add($time)
  735.     {
  736.         return $this->setFromSeconds(
  737.             $this->toSeconds() + $time->toSeconds()
  738.         );
  739.     }
  740.  
  741.     /**
  742.      * Subtracts a time span.
  743.      *
  744.      * Subtracts a time span. If the time span to subtract is larger
  745.      * than the original, the result is zero (there's no sense in
  746.      * negative time spans).
  747.      *
  748.      * @param  object Date_Span $time Time span to subtract.
  749.      *
  750.      * @access public
  751.      */
  752.     function subtract($time)
  753.     {
  754.         $sub = $this->toSeconds() - $time->toSeconds();
  755.         if ($sub < 0) {
  756.             $this->setFromSeconds(0);
  757.         } else {
  758.             $this->setFromSeconds($sub);
  759.         }
  760.     }
  761.  
  762.     /**
  763.      * Tells if time span is equal to $time.
  764.      *
  765.      * @param  object Date_Span $time Time span to compare to.
  766.      *
  767.      * @return bool   True if the time spans are equal.
  768.      *
  769.      * @access public
  770.      */
  771.     function equal($time)
  772.     {
  773.         return $this->toSeconds() == $time->toSeconds();
  774.     }
  775.  
  776.     /**
  777.      * Tells if this time span is greater or equal than $time.
  778.      *
  779.      * @param  object Date_Span $time Time span to compare to.
  780.      *
  781.      * @return bool   True if this time span is greater or equal than $time.
  782.      *
  783.      * @access public
  784.      */
  785.     function greaterEqual($time)
  786.     {
  787.         return $this->toSeconds() >= $time->toSeconds();
  788.     }
  789.  
  790.     /**
  791.      * Tells if this time span is lower or equal than $time.
  792.      *
  793.      * @param  object Date_Span $time Time span to compare to.
  794.      *
  795.      * @return bool   True if this time span is lower or equal than $time.
  796.      *
  797.      * @access public
  798.      */
  799.     function lowerEqual($time)
  800.     {
  801.         return $this->toSeconds() <= $time->toSeconds();
  802.     }
  803.  
  804.     /**
  805.      * Tells if this time span is greater than $time.
  806.      *
  807.      * @param  object Date_Span $time Time span to compare to.
  808.      *
  809.      * @return bool   True if this time span is greater than $time.
  810.      *
  811.      * @access public
  812.      */
  813.     function greater($time)
  814.     {
  815.         return $this->toSeconds() > $time->toSeconds();
  816.     }
  817.  
  818.     /**
  819.      * Tells if this time span is lower than $time.
  820.      *
  821.      * @param  object Date_Span $time Time span to compare to.
  822.      *
  823.      * @return bool   True if this time span is lower than $time.
  824.      *
  825.      * @access public
  826.      */
  827.     function lower($time)
  828.     {
  829.         return $this->toSeconds() < $time->toSeconds();
  830.     }
  831.  
  832.     /**
  833.      * Compares two time spans.
  834.      *
  835.      * Compares two time spans. Suitable for use in sorting functions.
  836.      *
  837.      * @param  object Date_Span $time1 The first time span.
  838.      * @param  object Date_Span $time2 The second time span.
  839.      *
  840.      * @return int    0 if the time spans are equal, -1 if time1 is lower
  841.      *                than time2, 1 if time1 is greater than time2.
  842.      *
  843.      * @static
  844.      * @access public
  845.      */
  846.     function compare($time1, $time2)
  847.     {
  848.         if ($time1->equal($time2)) {
  849.             return 0;
  850.         } elseif ($time1->lower($time2)) {
  851.             return -1;
  852.         } else {
  853.             return 1;
  854.         }
  855.     }
  856.  
  857.     /**
  858.      * Tells if the time span is empty (zero length).
  859.      *
  860.      * @return bool True is it's empty.
  861.      */
  862.     function isEmpty()
  863.     {
  864.         return !$this->day && !$this->hour && !$this->minute && !$this->second;
  865.     }
  866.  
  867.     /**
  868.      * Set the default input format.
  869.      *
  870.      * @param  mixed $format New default input format.
  871.      *
  872.      * @return mixed Previous default input format.
  873.      *
  874.      * @static
  875.      */
  876.     function setDefaultInputFormat($format)
  877.     {
  878.         $old = $GLOBALS['_DATE_SPAN_INPUT_FORMAT'];
  879.         $GLOBALS['_DATE_SPAN_INPUT_FORMAT'] = $format;
  880.         return $old;
  881.     }
  882.  
  883.     /**
  884.      * Get the default input format.
  885.      *
  886.      * @return mixed Default input format.
  887.      *
  888.      * @static
  889.      */
  890.     function getDefaultInputFormat()
  891.     {
  892.         return $GLOBALS['_DATE_SPAN_INPUT_FORMAT'];
  893.     }
  894.  
  895.     /**
  896.      * Set the default format.
  897.      *
  898.      * @param  mixed $format New default format.
  899.      *
  900.      * @return mixed Previous default format.
  901.      *
  902.      * @static
  903.      */
  904.     function setDefaultFormat($format)
  905.     {
  906.         $old = $GLOBALS['_DATE_SPAN_FORMAT'];
  907.         $GLOBALS['_DATE_SPAN_FORMAT'] = $format;
  908.         return $old;
  909.     }
  910.  
  911.     /**
  912.      * Get the default format.
  913.      *
  914.      * @return mixed Default format.
  915.      *
  916.      * @static
  917.      */
  918.     function getDefaultFormat()
  919.     {
  920.         return $GLOBALS['_DATE_SPAN_FORMAT'];
  921.     }
  922.  
  923.     /**
  924.      * Returns a copy of the object (workarround for PHP5 forward compatibility).
  925.      *
  926.      * @return object Date_Span Copy of the object.
  927.      */
  928.     function __clone() {
  929.         $c = get_class($this);
  930.         $s = new $c;
  931.         $s->day    = $this->day;
  932.         $s->hour   = $this->hour;
  933.         $s->minute = $this->minute;
  934.         $s->second = $this->second;
  935.         return $s;
  936.     }
  937. }
  938.  
  939. ?>
  940.